package com.googlecode.gwtbb.client.only.widget.basic;

import com.google.gwt.user.client.ui.*;
import com.googlecode.gwtbb.client.only.GwtbbCmess;
import com.googlecode.gwtbb.client.shared.entity.picture.Picture;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Abraham Grief
 * @version $Id$
 * @since Dec 29, 2008
 */
public class MultiPictureFileUpload extends Composite {
	private static final IconBundle icons = GwtbbBundle.icons();
	private HorizontalPanel mainPanel;
	private String formAction;
	private int maxNumPictures;
	private CaptionFetcherFactory captionFetcherFactory;
	private ArrayList<PictureFileUpload> pictureFileUploads;

	private AsyncFileUploadListenerCollection asyncFileUploadListeners;

	public MultiPictureFileUpload(String formAction, int maxNumPictures, CaptionFetcherFactory captionFetcherFactory) {
		this.formAction = formAction;
		this.maxNumPictures = maxNumPictures;
		this.captionFetcherFactory = captionFetcherFactory;

		asyncFileUploadListeners = new AsyncFileUploadListenerCollection();
		mainPanel = new HorizontalPanel();
		initWidget(mainPanel);
		mainPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
		pictureFileUploads = new ArrayList<PictureFileUpload>();
		addPictureFileUpload();
	}

	public List<PictureFileUpload> getPictureFileUploads() {
		return pictureFileUploads;
	}

	public void addAsyncFileUploadEventListener(AsyncFileUploadListener listener) {
		asyncFileUploadListeners.add(listener);
	}

	public void clear() {
		mainPanel.clear();
		pictureFileUploads.clear();
	}

	public boolean isEmpty() {
		for (PictureFileUpload pfu : pictureFileUploads)
			if (!pfu.isEmpty())
				return false;
		return true;
	}

	public boolean isUploading() {
		for (PictureFileUpload pfu : pictureFileUploads)
			if (pfu.isUploading())
				return true;
		return false;
	}

	public void removeAsyncFileUploadEventListener(AsyncFileUploadListener listener) {
		asyncFileUploadListeners.remove(listener);
	}

	public void reset() {
		clear();
		addPictureFileUpload();
	}

	public void setPictures(List<Picture> pictures) {
		clear();
		if (pictures != null)
			for (Picture picture : pictures) {
				PictureFileUpload pfu = addPictureFileUpload();
				pfu.setPicture(picture);
			}
		addPictureFileUpload();
		// first pfu should have left button disabled if it has a pic
		updateDirectionButtons(pictureFileUploads.get(0), 0);
	}

	private PictureFileUpload addPictureFileUpload() {
		PictureFileUpload retVal = null;
		final int numPfus = pictureFileUploads.size();
		if (numPfus < maxNumPictures) {
			String addPictureText;
			if (numPfus == 0) {
				addPictureText = GwtbbCmess.instance().addPicture();
			} else {
				addPictureText = GwtbbCmess.instance().addAnotherPicture();
				mainPanel.add(new Spacer());
			}
			final CaptionFetcher captionFetcher = captionFetcherFactory.constructCaptionFetcher();
			final PushButton leftButton = new PushButton(icons.arrowLeft().createImage());

			final PushButton rightButton = new PushButton(icons.arrowRight().createImage());
			final PictureFileUpload pfu = new PictureFileUpload(formAction, captionFetcher, addPictureText) {
				@Override
				public void onUploading(String fileName) {
					super.onUploading(fileName);
					int pfuIndex = findPfuIndex(this);
					updateDirectionButtons(this, pfuIndex);
					if (pfuIndex > 0)
						updateDirectionButtons(pictureFileUploads.get(pfuIndex - 1), pfuIndex - 1);
				}
			};
			pfu.addSideWidget(leftButton);
			pfu.addSideWidget(rightButton);

			leftButton.addClickListener(new ClickListener() {
				public void onClick(Widget sender) {
					int index = findPfuIndex(pfu);
					if (index > 0) {
						swapPfus(pfu, index, index - 1);
					}
				}
			});
			rightButton.addClickListener(new ClickListener() {
				public void onClick(Widget sender) {
					int index = findPfuIndex(pfu);
					if (index < pictureFileUploads.size() - 1) {
						swapPfus(pfu, index, index + 1);
					}
				}
			});

			mainPanel.add(pfu);
			pictureFileUploads.add(pfu);
			retVal = pfu;
			pfu.addAsyncFileUploadEventListener(new AsyncFileUploadListener() {
				public void onError(AsyncFileUploadErrorEvent event) {
					asyncFileUploadListeners.fireOnError(this, event.getErrorMessage());
				}

				public void onValidateFileName(AsyncFileUploadValidateFileNameEvent event) {
					AsyncFileUploadValidateFileNameEvent validateEvent = asyncFileUploadListeners.fireOnValidateFileName(event.getSource(), event.getFileName());
					event.setInvalid(validateEvent.isInvalid());
				}

				public void onSubmit(FormSubmitEvent event) {
					pfu.activateFetchCaption();
					addPictureFileUpload();
					event.setCancelled(asyncFileUploadListeners.fireOnSubmit((FormPanel)event.getSource()));
				}

				public void onSubmitComplete(FormSubmitCompleteEvent event) {
					asyncFileUploadListeners.fireOnComplete((FormPanel)event.getSource(), event.getResults());
				}
			});
		}
		return retVal;
	}

	private int findPfuIndex(PictureFileUpload pfu) {
		int index = 0;
		while (pfu != pictureFileUploads.get(index))
			index++;
		return index;
	}

	private void redisplayPictureFileUploads() {
		mainPanel.clear();
		boolean noSpacer = true;
		for (PictureFileUpload pfu : pictureFileUploads) {
			if (noSpacer) {
				noSpacer = false;
			} else {
				mainPanel.add(new Spacer());
			}
			mainPanel.add(pfu);
		}
	}

	private void swapPfus(PictureFileUpload pfu, int index, int swapIndex) {
		PictureFileUpload swapPfu = pictureFileUploads.get(swapIndex);
		if (pfu != null && !pfu.isEmpty() && swapPfu != null && !swapPfu.isEmpty()) {
			pictureFileUploads.set(index, swapPfu);
			pictureFileUploads.set(swapIndex, pfu);
			updateDirectionButtons(pfu, swapIndex);
			updateDirectionButtons(swapPfu, index);
			redisplayPictureFileUploads();
		}
	}

	private void updateDirectionButtons(PictureFileUpload pfu, int index) {
		PushButton leftButton = (PushButton)pfu.getSideWidget(0);
		leftButton.setEnabled(index > 0);
		PushButton rightButton = (PushButton)pfu.getSideWidget(1);
		if (index < pictureFileUploads.size() - 1) {
			PictureFileUpload rightPfu = pictureFileUploads.get(index + 1);
			rightButton.setEnabled(!rightPfu.isEmpty());
		} else {
			rightButton.setEnabled(false);
		}
	}
}
